package com.zgjkhis.modules.charges.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.zgjkhis.common.service.impl.BaseServiceImpl;
import com.zgjkhis.domain.PageResult;
import com.zgjkhis.exception.ServiceException;
import com.zgjkhis.modules.basicsetting.domain.OtherCharge;
import com.zgjkhis.modules.basicsetting.domain.Treatment;
import com.zgjkhis.modules.basicsetting.service.OtherChargeService;
import com.zgjkhis.modules.basicsetting.service.TreatmentService;
import com.zgjkhis.modules.charges.domain.*;
import com.zgjkhis.modules.charges.service.*;
import com.zgjkhis.modules.charges.service.dto.*;
import com.zgjkhis.modules.charges.service.mapper.PrescriptionOrderMapper;
import com.zgjkhis.modules.enums.AdditionalEnum;
import com.zgjkhis.modules.enums.InfoTypeEnum;
import com.zgjkhis.modules.enums.OrderChargeTypeEnum;
import com.zgjkhis.modules.enums.OrderTypeEnum;
import com.zgjkhis.modules.member.domain.Member;
import com.zgjkhis.modules.outpatient.domain.Account;
import com.zgjkhis.modules.outpatient.dto.LocalOrderDto;
import com.zgjkhis.modules.outpatient.dto.RefundComfireDto;
import com.zgjkhis.modules.outpatient.dto.ReissueDto;
import com.zgjkhis.modules.outpatient.service.AccountService;
import com.zgjkhis.modules.outpatient.service.dto.OrderDto;
import com.zgjkhis.modules.security.security.LoginUserUtil;
import com.zgjkhis.modules.system.domain.*;
import com.zgjkhis.modules.system.service.*;
import com.zgjkhis.modules.util.CharUtil;
import com.zgjkhis.modules.valid.ValidList;
import com.zgjkhis.utils.DateUtils;
import com.zgjkhis.utils.RandomUtils;
import com.zgjkhis.utils.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author yxl
 * @Description 处方订单Service
 * @Date 2021/7/13  15:38
 **/
@Service
public class PrescriptionServiceImpl extends BaseServiceImpl<PrescriptionOrderMapper, PrescriptionOrder> implements PrescriptionService {

    @Resource
    private InfoDrugService infoDrugService;
    @Resource
    private DrugService drugService;
    @Resource
    private PrescriptionRefundService prescriptionRefundService;
    @Resource
    private PrescriptionRefundDetailService prescriptionRefundDetailService;
    @Resource
    private DrugWareHousingDetailService drugWareHousingDetailService;
    @Resource
    private OrderComfireService orderComfireService;
    @Resource
    private InfoService infoService;
    @Resource
    private ConsultService consultService;
    @Resource
    private AccountService accountService;
    @Resource
    private TreatmentService treatmentService;
    @Resource
    private OtherChargeService otherChargeService;
    @Resource
    private PrescriptionChargeService prescriptionChargeService;
    @Resource
    private DictDetailService dictDetailService;
    @Resource
    private OrderAddressService orderAddressService;
    @Resource
    private LogisticsService logisticsService;

    @Resource
    private PrescriptionOrderPrintService prescriptionOrderPrintService;

    @Override
    public PageResult<PrescriptionOrderDto> findAllByPageable(PrescriptionQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        List<PrescriptionOrderDto> allByPageable = baseMapper.findAllByPageable(criteria);
        PageInfo<PrescriptionOrderDto> page = new PageInfo<>(allByPageable);
        return PageResult.data(page);
    }

    @Override
    public PageResult<LocalOrderDto> findAllByPageableForLocal(PrescriptionQueryCriteria criteria, Pageable pageable) {
        List<OrderAddress> addresses = orderAddressService.list(Wrappers.<OrderAddress>query().lambda().like(OrderAddress::getUsername, criteria.getUserName()));
        if (!CharUtil.isEmpty(addresses)) {
            List<String> orderNos = addresses.stream().map(OrderAddress::getOrderNo).collect(Collectors.toList());
            criteria.setOrderNos(orderNos);
        }
        getPage(pageable);
        List<LocalOrderDto> allByPageable = new ArrayList<>();
        if (CharUtil.isEmpty(criteria.getOrderType()) || "1".equals(criteria.getOrderType())) {
            allByPageable = baseMapper.findAllByPageableForLocal(criteria);
        } else {
            allByPageable = baseMapper.findAllByPageableForYun(criteria);
        }
        PageInfo<LocalOrderDto> page = new PageInfo<>(allByPageable);
        for (LocalOrderDto orderDto : allByPageable) {
            List<InfoDto> list = infoService.queryListByOrderNo(orderDto.getOrderNo());
            orderDto.setInfos(list);
            //需要发货 ==>发货管理
            if (criteria.getIsFlag() != null && 1 == criteria.getIsFlag()) {
                OrderAddress orderAddress = orderAddressService.getOne(Wrappers.<OrderAddress>query().lambda().eq(OrderAddress::getOrderNo, orderDto.getOrderNo()));
                orderDto.setOrderAddress(orderAddress);
                Logistics logistics = logisticsService.getOne(Wrappers.<Logistics>query().lambda().eq(Logistics::getOrderNo, orderDto.getOrderNo()).orderByDesc(Logistics::getCreateTime).last("limit 0,1"));
                if (!CharUtil.isEmpty(logistics)) {
                    orderDto.setLastMailNo(logistics.getMailNo());
                    orderDto.setLastMailTime(logistics.getCreateTime());
                }
            }
            long count = prescriptionOrderPrintService.count(Wrappers.<PrescriptionOrderPrint>query().lambda().eq(PrescriptionOrderPrint::getOrderNo, orderDto.getOrderNo()));
            orderDto.setPrintCount((int) count);

        }

        return PageResult.data(page);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void confirmOrder(PrescriptionOrder order) {
        List<InfoDrug> list = infoDrugService.list(Wrappers.<InfoDrug>query().lambda().eq(InfoDrug::getOrderNo, order.getOrderNo()));
        String errorMsg = "";
        for (InfoDrug infoDrug : list) {
            Drug drug = drugService.getOne(Wrappers.<Drug>query().lambda().eq(Drug::getId, infoDrug.getDrugId()).eq(Drug::getStatus, 0));
            if (CharUtil.isEmpty(drug)) {
                errorMsg = errorMsg + "" + infoDrug.getDrugName() + "不存在,或已被下架;";
                continue;
            }
            if (CharUtil.isEmpty(drug.getStock())) {
                drug.setStock(0);
            }
            infoDrug.setQuantity(infoDrug.getQuantity() - infoDrug.getRefundCount());//扣除已退个数
            if (infoDrug.getQuantity() > drug.getStock()) {
//                throw new ServiceException(String.format("药品【%s】库存不足,当前库存为%d", infoDrug.getDrugName(), drug.getStock()));
                errorMsg = errorMsg + infoDrug.getDrugName() + "库存不足;";
                continue;
            }

            //修改入库批次数量
            //获取有效期内，库存大于0的  按有效期升序排序
            if (infoDrug.getUseUnit().equals(infoDrug.getPackUnit()) || order.getOrderType().equals(OrderTypeEnum.ONLINE.getCode())) {//使用包装单位 或云享单
                int quantity = infoDrug.getQuantity();//包装单位数量
                List<DrugWareHousingDetail> drugWareHousingDetailList = drugWareHousingDetailService.queryComfireList(drug.getId());
                for (DrugWareHousingDetail drugWareHousingDetail : drugWareHousingDetailList) {
                    OrderComfire orderComfire = new OrderComfire();
                    orderComfire.setInfoDrugId(infoDrug.getId());
                    orderComfire.setWarehousingId(drugWareHousingDetail.getId());
                    orderComfire.setUseUnit(drug.getPackageUnit());
                    //顺位第一个入库大于扣减个数
                    if (drugWareHousingDetail.getLeftCount() >= quantity) {
                        DrugWareHousingDetail detail = new DrugWareHousingDetail();
                        detail.setId(drugWareHousingDetail.getId());
                        detail.setLeftCount(drugWareHousingDetail.getLeftCount() - quantity);
                        drugWareHousingDetailService.updateById(detail);
                        orderComfire.setDiveNum(quantity);
                        quantity = 0;
                    } else {
                        //顺位第一个入库小于扣减个数
                        quantity = quantity - drugWareHousingDetail.getLeftCount();
                        DrugWareHousingDetail detail = new DrugWareHousingDetail();
                        detail.setId(drugWareHousingDetail.getId());
                        detail.setLeftCount(0);
                        drugWareHousingDetailService.updateById(detail);
                        orderComfire.setDiveNum(drugWareHousingDetail.getLeftCount());
                    }

                    orderComfire.setPlusNum(orderComfire.getDiveNum());
                    orderComfireService.save(orderComfire);
                    if (quantity <= 0) {
                        break;
                    }
                }
                if (quantity > 0) {
                    errorMsg = errorMsg + infoDrug.getDrugName() + "库存不足;";
                    continue;
                } else {
                    drugService.updateMothUseById(drug.getId(), infoDrug.getQuantity(), 0);//修改月使用数
                    //出库修改药品数量
                    Drug tempDrug = new Drug();
                    tempDrug.setId(drug.getId());
                    tempDrug.setStock(drug.getStock() - infoDrug.getQuantity());
                    drugService.updateById(tempDrug);
                }
            } else if (infoDrug.getUseUnit().equals(infoDrug.getTotalDoseUnit())) {//剂量单位
                int minquantity = infoDrug.getMinQuantity() - infoDrug.getRefundCount();//剂量单位数量减去扣除数量
                //剂量单位扣除
                //获取剂量单位剩余列表
                List<DrugWareHousingDetail> drugWareHousingDetailList = drugWareHousingDetailService.queryComfireList(drug.getId());
                //拆分剂量单位数量扣除
                for (DrugWareHousingDetail drugWareHousingDetail : drugWareHousingDetailList) {
                    OrderComfire orderComfire = new OrderComfire();
                    orderComfire.setInfoDrugId(infoDrug.getId());
                    orderComfire.setWarehousingId(drugWareHousingDetail.getId());
                    orderComfire.setUseUnit(drug.getTotalDoseUnit());
                    //顺位第一个入库大于扣减个数
                    if (drugWareHousingDetail.getMinLeftCount() >= minquantity) {
                        DrugWareHousingDetail detail = new DrugWareHousingDetail();
                        detail.setId(drugWareHousingDetail.getId());
                        detail.setMinLeftCount(drugWareHousingDetail.getMinLeftCount() - minquantity);

                        drugWareHousingDetailService.updateById(detail);
                        orderComfire.setDiveNum(minquantity);
                        minquantity = 0;
                    } else {
                        //顺位第一个入库小于扣减个数
                        minquantity = minquantity - drugWareHousingDetail.getMinLeftCount();
                        DrugWareHousingDetail detail = new DrugWareHousingDetail();
                        detail.setId(drugWareHousingDetail.getId());
                        detail.setMinLeftCount(0);
                        drugWareHousingDetailService.updateById(detail);
                        orderComfire.setDiveNum(drugWareHousingDetail.getLeftCount());
                    }
                    orderComfire.setPlusNum(orderComfire.getDiveNum());
                    orderComfireService.save(orderComfire);
                    if (minquantity <= 0) {
                        break;
                    }
                }
                if (minquantity > 0) {
                    //剂量单位数量不够，从包装单位拆分补足
                    List<DrugWareHousingDetail> detailList = drugWareHousingDetailService.queryComfireList(drug.getId());
                    for (DrugWareHousingDetail drugWareHousingDetail : detailList) {
                        OrderComfire orderComfire = new OrderComfire();
                        orderComfire.setInfoDrugId(infoDrug.getId());
                        orderComfire.setWarehousingId(drugWareHousingDetail.getId());
                        orderComfire.setUseUnit(drug.getTotalDoseUnit());
                        //顺位第一个入库大于扣减个数
                        int minCount = drugWareHousingDetail.getLeftCount() * drug.getTotalDose();
                        if (minCount >= minquantity) {
                            int minLeftCount = minCount - minquantity;
                            int leftCount = (int) Math.floor(Double.valueOf(minLeftCount) / Double.valueOf(drug.getTotalDose()));
                            DrugWareHousingDetail detail = new DrugWareHousingDetail();
                            detail.setId(drugWareHousingDetail.getId());
                            detail.setLeftCount(leftCount);
                            detail.setMinLeftCount(minLeftCount - (leftCount * drug.getTotalDose()));
                            drugWareHousingDetailService.updateById(detail);
                            orderComfire.setDiveNum(minquantity);
                            minquantity = 0;
                        } else {
                            //顺位第一个入库小于扣减个数
                            minquantity = minquantity - minCount;
                            DrugWareHousingDetail detail = new DrugWareHousingDetail();
                            detail.setId(drugWareHousingDetail.getId());
                            detail.setLeftCount(0);
                            drugWareHousingDetailService.updateById(detail);
                            orderComfire.setDiveNum(drugWareHousingDetail.getLeftCount());
                        }
                        orderComfire.setPlusNum(orderComfire.getDiveNum());
                        orderComfireService.save(orderComfire);
                        if (minquantity <= 0) {
                            break;
                        }

                    }

                }
                if (minquantity > 0) {
                    errorMsg = errorMsg + infoDrug.getDrugName() + "库存不足;";
                    continue;
                } else {
                    drugService.updateMothUseById(drug.getId(), 0, infoDrug.getMinQuantity());//修改月使用数
                    //出库修改药品数量
                    drugService.updateStockById(drug.getId());
                }

            } else {
                throw new ServiceException("处方药品使用错误");
            }
        }
        // 返回204,药品错误列表
        if (!CharUtil.isEmpty(errorMsg)) {
            throw new ServiceException(errorMsg);
        }
        PrescriptionOrder prescriptionOrder = new PrescriptionOrder();
        prescriptionOrder.setId(order.getId());
//        prescriptionOrder.setPayStatus(5);
        prescriptionOrder.setOrderCondition(3);
        prescriptionOrder.setAdjustUserId(SecurityUtils.getUserId().toString());
        prescriptionOrder.setAdjustUser(LoginUserUtil.getNickName());
        prescriptionOrder.setAdjustTime(new Date());
        this.updateById(prescriptionOrder);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void refund(ValidList<PrescriptionRefundCriteria> prescriptionRefundCriteria, String msg, String orderNo) {

        PrescriptionOrder order = this.getOne(Wrappers.<PrescriptionOrder>query().lambda().eq(PrescriptionOrder::getId, orderNo).eq(PrescriptionOrder::getPharmacyId, LoginUserUtil.getPharmId()));
        if (CharUtil.isEmpty(order)) {
            throw new ServiceException("查无此订单");
        }
        if (order.getPayStatus() == 0) {
            throw new ServiceException("订单还未支付,退款失败");
        }
        if (order.getPayStatus() == 1) {
            throw new ServiceException("订单还未确认,退款失败");
        }
        if (order.getPayStatus() == 4) {
            throw new ServiceException("订单已全部退款,退款失败");
        }
        JSONArray array = new JSONArray();
        String refundNo = DateUtils.dateTimeNow() + RandomUtils.getRandomNumbers(6);
        List<PrescriptionRefundDetail> list = new ArrayList<>();
        BigDecimal total = BigDecimal.ZERO;
        for (PrescriptionRefundCriteria refundCriteria : prescriptionRefundCriteria) {

            PrescriptionRefundDetail prescriptionRefundDetail = new PrescriptionRefundDetail();

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("infoDrugId", refundCriteria.getInfoDrugId());
            InfoDrug infoDrug = infoDrugService.getById(refundCriteria.getInfoDrugId());
            if (CharUtil.isEmpty(infoDrug)) {
                jsonObject.put("message", "未找到详情id:" + refundCriteria.getInfoDrugId());
                array.add(jsonObject);
                continue;
            }
            Integer leftCount = infoDrug.getQuantity() - infoDrug.getRefundCount();
            if (leftCount < refundCriteria.getRefundNum()) {
                jsonObject.put("message", "退款个数大于剩余个数,剩余：" + leftCount);
                array.add(jsonObject);
                continue;
            }
            InfoDrug temp = new InfoDrug();
            temp.setId(infoDrug.getId());
            temp.setRefundCount(infoDrug.getRefundCount() + refundCriteria.getRefundNum());
            if (temp.getRefundCount() >= infoDrug.getQuantity()) {
                temp.setStatus(3);
            } else {
                temp.setStatus(2);
            }
            infoDrugService.updateById(temp);//修改详情

            List<OrderComfire> orderComfireList = orderComfireService.list(Wrappers.<OrderComfire>query().lambda()
                    .eq(OrderComfire::getInfoDrugId, infoDrug.getId()).gt(OrderComfire::getPlusNum, 0));

            int count = refundCriteria.getRefundNum();
            for (OrderComfire oc : orderComfireList) {
                OrderComfire orderComfire = new OrderComfire();
                orderComfire.setId(oc.getId());
                orderComfire.setInfoDrugId(infoDrug.getId());
                orderComfire.setWarehousingId(oc.getWarehousingId());
                DrugWareHousingDetail det = drugWareHousingDetailService.getById(oc.getWarehousingId());
                //顺位第一个入库大于扣减个数
                if (oc.getPlusNum() >= count) {
                    DrugWareHousingDetail detail = new DrugWareHousingDetail();
                    detail.setId(oc.getWarehousingId());
                    detail.setLeftCount(det.getLeftCount() + count);
                    drugWareHousingDetailService.updateById(detail);
                    orderComfire.setPlusNum(oc.getPlusNum() - count);
                    count = 0;
                    break;
                } else {
                    //顺位第一个入库小于扣减个数
                    count = count - oc.getPlusNum();
                    DrugWareHousingDetail detail = new DrugWareHousingDetail();
                    detail.setId(oc.getWarehousingId());
                    detail.setLeftCount(det.getLeftCount() + oc.getPlusNum());
                    drugWareHousingDetailService.updateById(detail);
                    orderComfire.setPlusNum(0);
                }
                orderComfireService.updateById(orderComfire);
            }

            //修改库存
            Drug drug = drugService.getById(infoDrug.getDrugId());
            Drug tempDrug = new Drug();
            tempDrug.setId(infoDrug.getDrugId());
            tempDrug.setStock(drug.getStock() + refundCriteria.getRefundNum());
            drugService.updateById(tempDrug);
            drugService.updateMothUseById(drug.getId(), 0 - refundCriteria.getRefundNum(), 0);

            //退款明细记录
            prescriptionRefundDetail.setRefundNum(refundCriteria.getRefundNum());
            prescriptionRefundDetail.setPharmacyId(LoginUserUtil.getPharmId());
            prescriptionRefundDetail.setBusinessId(infoDrug.getId().toString());
            prescriptionRefundDetail.setProjectId(infoDrug.getDrugId().toString());
            prescriptionRefundDetail.setName(infoDrug.getDrugName());
            prescriptionRefundDetail.setRefund(infoDrug.getDiscountPrice().multiply(BigDecimal.valueOf(refundCriteria.getRefundNum())));
            prescriptionRefundDetail.setRefundNo(refundNo);
            list.add(prescriptionRefundDetail);
            total = total.add(prescriptionRefundDetail.getRefund());
        }

        //返回204,退款列表错误 HttpStatus.NO_CONTENT
        if (!CharUtil.isEmpty(array) && array.size() > 0) {
            throw new ServiceException(array.toJSONString());
        }

        List<InfoDrug> infoDrugs = infoDrugService.list(Wrappers.<InfoDrug>query().lambda().eq(InfoDrug::getOrderNo, order.getOrderNo()));
        Integer payStatus = 3;
        int count = 0;
        for (InfoDrug infoDrug : infoDrugs) {
            if (infoDrug.getStatus() == 3) {
                count++;
            }
        }
        if (count >= infoDrugs.size()) {
            payStatus = 4;
        }
        PrescriptionOrder prescriptionOrder = new PrescriptionOrder();
        prescriptionOrder.setId(order.getId());
        prescriptionOrder.setPayStatus(payStatus);
        this.updateById(prescriptionOrder);
        //退款单记录
        PrescriptionRefund prescriptionRefund = new PrescriptionRefund();
        prescriptionRefund.setRefundNo(refundNo);
        prescriptionRefund.setRefundMsg(msg);
        prescriptionRefund.setOrderNo(order.getOrderNo());
        prescriptionRefund.setPharmacyId(LoginUserUtil.getPharmId());
        prescriptionRefund.setRefund(total);
        prescriptionRefundService.save(prescriptionRefund);
        prescriptionRefundDetailService.saveBatch(list);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrder(OrderDto orderDto) {
        if (CharUtil.isEmpty(orderDto.getConsult())) {
            throw new ServiceException("问诊不能为空");
        }
        if (CharUtil.isEmpty(orderDto.getConsult().getId())) {
            throw new ServiceException("问诊id不能为空");
        }
        Consult consult = consultService.getById(orderDto.getConsult().getId());
        if (CharUtil.isEmpty(consult)) {
            throw new ServiceException("无效问诊");
        }
        Account account = accountService.getById(orderDto.getConsult().getPatientId());

        PrescriptionOrder order = null;
        if (!CharUtil.isEmpty(orderDto.getOrderId())) {
            order = this.getById(orderDto.getOrderId());//获取订单
            if (CharUtil.isEmpty(order)) {
                throw new ServiceException("无效订单");
            }
        }
        if (CharUtil.isEmpty(order) || CharUtil.isEmpty(order.getId())) {
            String orderNo = DateUtils.dateTimeNow() + RandomUtils.getRandomNumbers(6);
            order = new PrescriptionOrder();
            order.setOrderNo(orderNo);
            order.setOrderTime(new Date());
            order.setDocName(orderDto.getConsult().getConsultDocName());
            order.setDocId(orderDto.getConsult().getConsultDocId());
            order.setPatientId(orderDto.getConsult().getId().toString());
            order.setPatientName(orderDto.getConsult().getPatientName());
            order.setPatientSex(account.getSex());
            order.setPatientAge(account.getAge().toString());
//            order.setDeliveryType(2);
            order.setPayStatus(0);
            order.setOrderStatus(0);
            order.setOrderType(1);
            order.setPharmacyId(LoginUserUtil.getPharmId());
            order.setConsultNo(consult.getConsultNo());
            order.setDepartmentId(orderDto.getConsult().getConsultDepartId());
            order.setDepartmentName(orderDto.getConsult().getConsultDepartName());
        } else {
            order.setDocName(orderDto.getConsult().getConsultDocName());
            order.setDocId(orderDto.getConsult().getConsultDocId());
            order.setPatientId(orderDto.getConsult().getId().toString());
            order.setPatientName(orderDto.getConsult().getPatientName());
            order.setDepartmentId(orderDto.getConsult().getConsultDepartId());
            order.setDepartmentName(orderDto.getConsult().getConsultDepartName());
        }
//        order.setTotalFee(BigDecimal.ZERO);//填充
//        order.setMachinFee(BigDecimal.ZERO);
//        order.setDrugCost(BigDecimal.ZERO);//药费，填充
        //更新问诊
        orderDto.getConsult().setConsultStatus(3);//就诊完成
        consultService.updateById(orderDto.getConsult());
        //判断用户是否会员
        Member member = null;
//        if(!"0".equals(account.getMembershipType())){
//             member=memberService.getById(account.getMembershipType());
//            if(CharUtil.isEmpty(member)){
//                throw  new ServiceException("用户会员信息错误");
//            }
//        }else{
//            member=null;
//        }
        //附加费用
        if (!CharUtil.isEmpty(orderDto.getPrescriptionCharge()) && orderDto.getPrescriptionCharge().size() > 0) {
            BigDecimal totalFee = savePrescriptionCharge(orderDto, order, member);
        }
        //处方费用
        saveInfoAndInfoDrug(orderDto, order, member);
        //保存订单
        this.saveOrUpdate(order);
        //修改订单价格统计
        updateOrderForMoney(order.getOrderNo(), null);

    }

    @Override
    public void updateOrderForMoney(String orderNO, Integer type) {
        PrescriptionOrder order = this.getOne(Wrappers.<PrescriptionOrder>query().lambda().eq(PrescriptionOrder::getOrderNo, orderNO));
        //修改附加费用
        OrderChargeDto orderChargeDto = baseMapper.queryOrderChargeFee(order.getOrderNo());
        //修改处方费用
        List<InfoDrugCostDto> list = infoDrugService.queryTotalFeeForInfo(order.getOrderNo());
        List<Info> infoList = new ArrayList<>();
        BigDecimal totalFee = BigDecimal.ZERO;
        BigDecimal processCost = BigDecimal.ZERO;
        for (InfoDrugCostDto infoDrugCost : list) {
            Info temp = infoService.getOne(Wrappers.<Info>query().lambda().eq(Info::getId, infoDrugCost.getInfoId()).eq(Info::getDeleteFlag, 0));
            Info info = new Info();
            info.setId(infoDrugCost.getInfoId());
            //药费
            info.setDrugCost(infoDrugCost.getTotalFee());
            String process = "0";
            info.setProcessCost(BigDecimal.ZERO);
            if (!CharUtil.isEmpty(temp.getPstType()) && !CharUtil.isEmpty(temp.getDosageForm()) && 1 == temp.getPstType() && 2 == temp.getDosageForm()) {
                process = dictDetailService.queryProcessCost("process_cost");
                //加工费
                info.setProcessCost(BigDecimal.valueOf(Double.valueOf(process)).multiply(BigDecimal.valueOf(temp.getNum())));
            } else if (!CharUtil.isEmpty(temp.getPstType()) && 5 == temp.getPstType()) {
                process = dictDetailService.queryProcessCost("gf_process_cost");
                //膏方加工费
                info.setProcessCost(BigDecimal.valueOf(Double.valueOf(process)));
            }
            info.setTotalPay(info.getDrugCost().add(info.getProcessCost()));
            infoList.add(info);
            totalFee = totalFee.add(infoDrugCost.getTotalFee());
            processCost = processCost.add(info.getProcessCost() == null ? BigDecimal.ZERO : info.getProcessCost());
        }
        PrescriptionOrder temp = new PrescriptionOrder();
        temp.setId(order.getId());
        //附加费
        temp.setOtherCost(orderChargeDto.getTotalFee());
        //药费
        temp.setDrugCost(totalFee);
        //加工费
        temp.setMachinFee(processCost);

        temp.setTotalFee(temp.getDrugCost().add(temp.getMachinFee()).add(temp.getOtherCost()));
        infoService.updateBatchById(infoList);//修改处方金额
        this.updateById(temp);
    }

    @Override
    public int waitCheck(String pharmacyId, Integer prescriptionType) {
        return this.baseMapper.waitCheck(pharmacyId, prescriptionType);
    }

    @Override
    public int waitRefund(String pharmacyId, Integer prescriptionType) {
        return this.baseMapper.waitRefund(pharmacyId, prescriptionType);
    }

    @Override
    public int waitPrint(String pharmacyId, Integer prescriptionType) {
        return this.baseMapper.waitPrint(pharmacyId, prescriptionType);
    }

    /**
     * 根据物流业务单号更改订单状态
     *
     * @param bspOrderNo
     */
    @Override
    public void updateOrderCondition(String bspOrderNo) {
        this.baseMapper.updateOrderCondition(bspOrderNo);
    }

    @Override
    public List<PrescriptionOrder> queryListByBspOrderNo(String bspOrderNo) {
        return baseMapper.queryListByBspOrderNo(bspOrderNo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void comfireStock(PrescriptionOrder order, RefundComfireDto refundComfireDto) {
        Integer type = 1;
        //获取未处理量大于0的数据
        List<InfoDrug> infoDrugs = infoDrugService.list(Wrappers.<InfoDrug>query().lambda().eq(InfoDrug::getOrderNo, refundComfireDto.getOrderNo()).gt(InfoDrug::getOperateNum, 0));
        //需要退库存
        if (refundComfireDto.getType() == 1) {
            for (InfoDrug infoDrug : infoDrugs) {
                refundDrugStock(infoDrug);
            }
        } else {
            type = 0;
        }


        //修改药品操作
        infoDrugService.update(Wrappers.<InfoDrug>update().lambda()
                .set(InfoDrug::getOperateNum, 0).set(InfoDrug::getRefundType, type)
                .eq(InfoDrug::getOrderNo, refundComfireDto.getOrderNo()).gt(InfoDrug::getOperateNum, 0)
        );
        this.update(Wrappers.<PrescriptionOrder>update().lambda().set(PrescriptionOrder::getRefundType, refundComfireDto.getType()).set(PrescriptionOrder::getRefundFlag, 2).eq(PrescriptionOrder::getOrderNo, refundComfireDto.getOrderNo()));


    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void reissue(Info info, ReissueDto reissueDto) {

        PrescriptionOrder order = this.getOne(Wrappers.<PrescriptionOrder>query().lambda().eq(PrescriptionOrder::getOrderNo, info.getOrderNo()));
        String orderNo = DateUtils.dateTimeNow() + RandomUtils.getRandomNumbers(6);
        String infoNo = DateUtils.dateTimeNow() + RandomUtils.getRandomNumbers(6);
        List<InfoDrug> list = new ArrayList<>();
        //颗粒剂，饮片
        if (info.getPrescriptionType().equals(InfoTypeEnum.ZYCFKLJ.getCode()) || info.getPrescriptionType().equals(InfoTypeEnum.ZYCF.getCode())) {
            List<InfoDrug> infoDrugs = infoDrugService.list(Wrappers.<InfoDrug>query().lambda().eq(InfoDrug::getInfoNo, info.getInfoNo()));
            for (InfoDrug infoDrug : infoDrugs) {
                InfoDrug temp = new InfoDrug();
                BeanUtils.copyProperties(infoDrug, temp);
                temp.setId(null);
                temp.setInfoNo(infoNo);
                temp.setOrderNo(orderNo);
                temp.setStatus(1);
                temp.setRefundCount(0);
                temp.setRefundType(0);
                temp.setIsCirulation(0);
                temp.setCirOrderNo(null);
                temp.setCirInfoNo(null);
                temp.setCirDrugId(null);
                temp.setOperateNum(0);
                temp.setDeleteFlag(0);
                temp.setIsCancel(0);
                temp.setCreateTime(new Date());
                temp.setQuantity(temp.getDose().multiply(BigDecimal.valueOf(reissueDto.getNum())).intValue());
                list.add(temp);
            }
        } else if (info.getPrescriptionType().equals(InfoTypeEnum.CYCF.getCode())) {
            if (CharUtil.isEmpty(reissueDto.getDrugList())) {
                throw new ServiceException("请选择需要补发的药品及数量");
            }
            //成药
            for (InfoDrug infoDrug : reissueDto.getDrugList()) {
                if (CharUtil.isEmpty(infoDrug.getId())) {
                    throw new ServiceException("补发药品参数ID不能为空");
                }
                InfoDrug drug = infoDrugService.getById(infoDrug.getId());
                if (CharUtil.isEmpty(drug)) {
                    throw new ServiceException("查无此药品：" + infoDrug.getDrugName());
                }
                if (!drug.getInfoNo().equals(reissueDto.getInfoNo())) {
                    throw new ServiceException("该处方没有该药品：" + drug.getDrugName());
                }
                InfoDrug temp = new InfoDrug();
                BeanUtils.copyProperties(drug, temp);
                temp.setId(null);
                temp.setInfoNo(infoNo);
                temp.setOrderNo(orderNo);
                temp.setStatus(1);
                temp.setRefundCount(0);
                temp.setRefundType(0);
                temp.setIsCirulation(0);
                temp.setCirOrderNo(null);
                temp.setCirInfoNo(null);
                temp.setCirDrugId(null);
                temp.setOperateNum(0);
                temp.setDeleteFlag(0);
                temp.setIsCancel(0);
                temp.setCreateTime(new Date());
                temp.setQuantity(infoDrug.getQuantity());
                list.add(temp);
            }
        }
        //处方
        Info tempInfo = new Info().copyInfo(orderNo, infoNo, info);
        tempInfo.setNum(reissueDto.getNum());
        //订单
        PrescriptionOrder tempOrder = new PrescriptionOrder().copyOrder(orderNo, order);
        tempOrder.setReissueReason(reissueDto.getReissueReason());
        //保存处方
        infoService.save(tempInfo);
        //保存处方详情
        infoDrugService.saveBatch(list);
        //保存订单
        this.saveOrUpdate(tempOrder);
        //修改订单价格统计
        updateOrderForMoney(tempOrder.getOrderNo(), null);
        //设置实际收费：0
        this.update(Wrappers.<PrescriptionOrder>update().lambda().set(PrescriptionOrder::getActualCharge, 0).eq(PrescriptionOrder::getOrderNo, orderNo));
        OrderAddress orderAddress = orderAddressService.getOne(Wrappers.<OrderAddress>query().lambda().eq(OrderAddress::getOrderNo, order.getOrderNo()));
        if (!CharUtil.isEmpty(orderAddress)) {
            OrderAddress tempOrderAddress = new OrderAddress();
            BeanUtils.copyProperties(orderAddress, tempOrderAddress);
            tempOrderAddress.setOrderNo(orderNo);
            tempOrderAddress.setCreateTime(new Date());
            orderAddressService.save(tempOrderAddress);
        }
    }


    /**
     * 退库存操作
     *
     * @param infoDrug
     */
    private void refundDrugStock(InfoDrug infoDrug) {
        List<OrderComfire> orderComfireList = orderComfireService.list(Wrappers.<OrderComfire>query().lambda()
                .eq(OrderComfire::getInfoDrugId, infoDrug.getId()).gt(OrderComfire::getPlusNum, 0));
        int count = infoDrug.getOperateNum();
        int tempcount = count;
        for (OrderComfire oc : orderComfireList) {
            OrderComfire orderComfire = new OrderComfire();
            orderComfire.setId(oc.getId());
            orderComfire.setInfoDrugId(infoDrug.getId());
            orderComfire.setWarehousingId(oc.getWarehousingId());
            DrugWareHousingDetail det = drugWareHousingDetailService.getById(oc.getWarehousingId());
            //顺位第一个入库大于扣减个数
            if (oc.getPlusNum() >= count) {
                DrugWareHousingDetail detail = new DrugWareHousingDetail();
                detail.setId(oc.getWarehousingId());
                detail.setLeftCount(det.getLeftCount() + count);
                drugWareHousingDetailService.updateById(detail);
                orderComfire.setPlusNum(oc.getPlusNum() - count);
                count = 0;
                orderComfireService.updateById(orderComfire);
                break;
            } else {
                //顺位第一个入库小于扣减个数
                count = count - oc.getPlusNum();
                DrugWareHousingDetail detail = new DrugWareHousingDetail();
                detail.setId(oc.getWarehousingId());
                detail.setLeftCount(det.getLeftCount() + oc.getPlusNum());
                drugWareHousingDetailService.updateById(detail);
                orderComfire.setPlusNum(0);
                orderComfireService.updateById(orderComfire);
            }

        }

        //修改库存
        Drug drug = drugService.getById(infoDrug.getDrugId());
        Drug tempDrug = new Drug();
        tempDrug.setId(infoDrug.getDrugId());
        tempDrug.setStock(drug.getStock() + tempcount);
        drugService.updateById(tempDrug);
    }


    /**
     * @return void
     * @Author yzq
     * @Description 保存处方, 处方详情
     * @Date 2021/9/9 14:07
     * @Param [orderDto, order, member]
     **/
    private void saveInfoAndInfoDrug(OrderDto orderDto, PrescriptionOrder order, Member member) {
        List<Info> infoList = new ArrayList<>();
        List<InfoDrug> infoDrugs = new ArrayList<>();
        for (Info info : orderDto.getInfo()) {
            //判断处方是否支付
            if (!CharUtil.isEmpty(info.getId())) {
                Info temp = infoService.getOne(Wrappers.<Info>query().lambda().eq(Info::getId, info.getId()).eq(Info::getDeleteFlag, 0));
                if (!CharUtil.isEmpty(temp) && temp.getPayStatus() != 0) {
                    continue;
                }
                info.setInfoNo(temp.getInfoNo());
            }
            if (info.getPrescriptionType() == 1 && CharUtil.isEmpty(info.getPstType()) && CharUtil.isEmpty(info.getDosageForm())) {
                throw new ServiceException("中药饮片处方中处方类型、剂型不能为空");
            }
            info.setPharmacyId(LoginUserUtil.getPharmId());
            info.setOrderNo(order.getOrderNo());
            info.setPayStatus(0);
            info.setDocId(order.getDocId());
            info.setDocName(order.getDocName());
            info.setPatientId(order.getPatientId());
            info.setPatientName(order.getPatientName());
            info.setConsultNo(order.getConsultNo());
            info.setPharmacyId(LoginUserUtil.getPharmId());
            if (CharUtil.isEmpty(info.getId())) {
                String infoNo = DateUtils.dateTimeNow() + RandomUtils.getRandomNumbers(6);
                info.setInfoNo(infoNo);
                info.setIsPosted(2);
            }
            //处理处方药材
            for (InfoDrug infoDrug : info.getInfoDrugs()) {
                if (!CharUtil.isEmpty(infoDrug.getId())) {
                    InfoDrug temp = infoDrugService.getById(infoDrug.getId());
                    if (!CharUtil.isEmpty(temp) && temp.getStatus() != 0) {
                        continue;
                    }
                }
                if (CharUtil.isEmpty(infoDrug.getDose())) {
                    throw new ServiceException("一次剂量不能为空");
                }
                infoDrug.setOrderNo(order.getOrderNo());
                infoDrug.setInfoNo(info.getInfoNo());
                infoDrug.setPharmacyId(LoginUserUtil.getPharmId());
                infoDrug.setStatus(0);
                infoDrug.setRefundCount(0);
                Drug drug = drugService.getOne(Wrappers.<Drug>query().lambda().eq(Drug::getId, infoDrug.getDrugId()).eq(Drug::getStatus, 0));
                if (CharUtil.isEmpty(drug)) {
                    throw new ServiceException("药品【" + infoDrug.getDrugName() + "】不存在");
                }
                if (CharUtil.isEmpty(infoDrug.getUseUnit()) || (!infoDrug.getUseUnit().equals(drug.getPackageUnit()) && !infoDrug.getUseUnit().equals(drug.getTotalDoseUnit()))) {
                    throw new ServiceException("材料费用【" + infoDrug.getDrugName() + "】单位错误");
                }
                infoDrug.setDrugName(drug.getDrugName());
                infoDrug.setSpecification(drug.getDrugSpec());
                infoDrug.setDoseUnit(drug.getDoseUnit());
                infoDrug.setPrice(drug.getSalePrice());
                infoDrug.setPackUnit(drug.getPackageUnit());
                infoDrug.setTotalDoseUnit(drug.getTotalDoseUnit());
                Integer discount = CharUtil.isEmpty(member) ? 100 : member.getPrescriptionOrderDiscount();
                infoDrug.setDiscount((discount / 100) + "");
                infoDrug.setDiscountPrice(infoDrug.getPrice().multiply(BigDecimal.valueOf((discount / 100))));
                if (info.getPrescriptionType().equals(InfoTypeEnum.CYCF.getCode())) {
                    //成药
                    if (CharUtil.isEmpty(infoDrug.getQuantity())) {
                        throw new ServiceException(infoDrug.getDrugName() + "开药量不能为空");
                    }
                } else if (info.getPrescriptionType().equals(InfoTypeEnum.ZYCF.getCode()) || info.getPrescriptionType().equals(InfoTypeEnum.ZYCFKLJ.getCode())) {
                    //中药处方
                    infoDrug.setQuantity((BigDecimal.valueOf(infoDrug.getQuantity()).multiply(BigDecimal.valueOf(info.getNum()))).intValue());
                }
                if (infoDrug.getQuantity() > drug.getStock()) {
                    throw new ServiceException("药品【" + drug.getDrugName() + "】库存不足");
                }
                infoDrugs.add(infoDrug);
            }
            info.setInfoDrugs(infoDrugs);
            infoList.add(info);
        }
        infoService.saveOrUpdateBatch(infoList);//保存处方
        infoDrugService.saveOrUpdateBatch(infoDrugs);//保存处方详情
    }

    /**
     * @return java.math.BigDecimal
     * @Author yzq
     * @Description 保存附加费用
     * @Date 2021/9/9 11:32
     * @Param [orderDto, order, member]
     **/
    private BigDecimal savePrescriptionCharge(OrderDto orderDto, PrescriptionOrder order, Member member) {
        List<PrescriptionCharge> chargeList = new ArrayList<>();
        BigDecimal totalFee = BigDecimal.ZERO;
        for (PrescriptionCharge charge : orderDto.getPrescriptionCharge()) {
            if (!CharUtil.isEmpty(charge.getId())) {
                PrescriptionCharge temp = prescriptionChargeService.getById(charge.getId());
                if (!CharUtil.isEmpty(temp) && temp.getStatus() != 0) {
                    continue;
                }
            }
            charge.setPharmacyId(LoginUserUtil.getPharmId());
            charge.setOrderNo(order.getOrderNo());
            charge.setRefundCount(0);
            charge.setStatus(0);
            String projectId = charge.getProjectId();
            Integer type = charge.getType();
            if (type.equals(AdditionalEnum.CL.getCode())) {//材料费用
                Drug drug = drugService.getOne(Wrappers.<Drug>query().lambda().eq(Drug::getId, projectId).eq(Drug::getStatus, 0));
                if (CharUtil.isEmpty(drug)) {
                    throw new ServiceException("【" + charge.getProjectName() + "】不存在");
                }
                if (CharUtil.isEmpty(charge.getUseUnit()) || (!charge.getUseUnit().equals(drug.getPackageUnit()) && !charge.getUseUnit().equals(drug.getTotalDoseUnit()))) {
                    throw new ServiceException("材料费用【" + charge.getProjectName() + "】单位错误");
                }
                charge.setSpec(drug.getDrugSpec());
                charge.setProjectName(drug.getDrugName());
                if (charge.getUseUnit().equals(drug.getPackageUnit())) {//包装单位
                    charge.setPrice(drug.getSalePrice());//包装价格
                } else {//零售单位
                    charge.setPrice(drug.getSellPiecePrice());//零售价格
                }
                Integer discount = CharUtil.isEmpty(member) ? 100 : member.getMaterialCostDiscount();
                charge.setDiscount((discount / 100) + "");
                charge.setDiscountPrice(charge.getPrice().multiply(BigDecimal.valueOf(discount / 100)));
                charge.setTotalPrice(charge.getDiscountPrice().multiply(BigDecimal.valueOf(charge.getQuantity())));//总价格
            } else if (type.equals(AdditionalEnum.ZL.getCode())) {//治疗项目
                Treatment treatment = treatmentService.getOne(Wrappers.<Treatment>query().lambda().eq(Treatment::getId, projectId).eq(Treatment::getSalePrice, 0));
                if (CharUtil.isEmpty(treatment)) {
                    throw new ServiceException("【" + charge.getProjectName() + "】不存在");
                }
                charge.setProjectName(treatment.getProjectName());
                charge.setUseUnit(treatment.getCompany());
                charge.setPrice(treatment.getSalePrice());
                if (treatment.getIsDiscount() == 0) {//允许折扣
                    Integer discount = CharUtil.isEmpty(member) ? 100 : member.getMaterialCostDiscount();
                    charge.setDiscount((discount / 100) + "");
                    charge.setDiscountPrice(charge.getPrice().multiply(BigDecimal.valueOf(discount / 100)));
                } else {
                    charge.setDiscount("1");//折扣
                    charge.setDiscountPrice(charge.getPrice());
                }
                charge.setTotalPrice(charge.getDiscountPrice().multiply(BigDecimal.valueOf(charge.getQuantity())));//总价格
            } else {//检验检查  其他
                OtherCharge otherCharge = otherChargeService.getOne(Wrappers.<OtherCharge>query().lambda().eq(OtherCharge::getId, projectId).eq(OtherCharge::getStatus, 0));
                if (CharUtil.isEmpty(otherCharge)) {
                    throw new ServiceException("【" + charge.getProjectName() + "】不存在");
                }
                charge.setProjectName(otherCharge.getProjectName());
                charge.setUseUnit(otherCharge.getCompany());
                charge.setPrice(otherCharge.getSalePrice());
                if (otherCharge.getIsDiscount() == 0) {//允许折扣
                    Integer discount = 100;
                    if (CharUtil.isEmpty(member)) {
                        if (otherCharge.getType().equals(OrderChargeTypeEnum.JY.getCode())) {//检验
                            discount = member.getInspectionDiscount();
                        } else if (otherCharge.getType().equals(OrderChargeTypeEnum.JC.getCode())) {
                            discount = member.getCheckDiscount();
                        } else if (otherCharge.getType().equals(OrderChargeTypeEnum.Other.getCode())) {
                            discount = member.getOtherExpensesDiscount();
                        }
                        if (CharUtil.isEmpty(discount)) {
                            discount = 100;
                        }
                    }
                    charge.setDiscount((discount / 100) + "");
                    charge.setDiscountPrice(charge.getPrice().multiply(BigDecimal.valueOf(discount / 100)));
                } else {
                    charge.setDiscount("1");//折扣
                    charge.setDiscountPrice(charge.getPrice());
                }
                charge.setTotalPrice(charge.getDiscountPrice().multiply(BigDecimal.valueOf(charge.getQuantity())));//总价
            }
            totalFee = totalFee.add(charge.getTotalPrice());
            chargeList.add(charge);
        }
        prescriptionChargeService.saveOrUpdateBatch(chargeList);
        return totalFee;
    }

}
